package com.zws.cucumber.plugin.snapshot;

import com.zws.cucumber.plugin.ZwsPlugin;
import com.zws.cucumber.util.colorfullog.ZwsColorfulLogger;
import io.cucumber.core.runner.CoreRunnerSnapshotTestCaseHelper;
import io.cucumber.plugin.event.EventPublisher;
import io.cucumber.plugin.event.TestCase;
import io.cucumber.plugin.event.TestCaseStarted;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

public class ZwsSnapshotPluginImpl implements ZwsPlugin {

    private static final Logger logger = ZwsColorfulLogger.of(LoggerFactory.getLogger(ZwsSnapshotPluginImpl.class));

    private static volatile boolean globalEnable = false;

    private static volatile String lastFeaturePath = null;
    private static boolean hasBackground = false;

    public static void setGlobalEnable(boolean globalEnable) {
        ZwsSnapshotPluginImpl.globalEnable = globalEnable;
    }

    public static void handleTestCaseStarted(TestCaseStarted event) {
        try {
            handleTestCaseStarted0(event);
        } catch (Throwable e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static void handleTestCaseStarted0(TestCaseStarted event) {
        TestCase testCase = event.getTestCase();

        logger.info("test case \"{}\" with tags {}", testCase.getName(), testCase.getTags());
        if (testCase.getTags().contains("@Procedure")) {
            logger.debug("skip scenario have @Procedure");
            return;
        }

        boolean localEnable = globalEnable;
        if (globalEnable) {
            if (testCase.getTags().contains("@DisableOptimization")) {
                localEnable = false;
            }
        } else {
            if (testCase.getTags().contains("@EnableOptimization")) {
                localEnable = true;
            }
        }
        if (globalEnable != localEnable) {
            logger.debug("optimization is <y>{}</y> locally, globalEnable: {}, localEnable: {}",
                    localEnable ? "enabled" : "disabled", globalEnable, localEnable);
        }
        if (!localEnable) {
            return;
        }

        String currentFeaturePath = CoreRunnerSnapshotTestCaseHelper.getFeaturePath(testCase);
        logger.debug("featurePath: {}", CoreRunnerSnapshotTestCaseHelper.getFeaturePath(testCase));
        if (Objects.equals(lastFeaturePath, currentFeaturePath)) {
            if (hasBackground) {
                logger.debug("skip background step and inject snapshot restore step");
                CoreRunnerSnapshotTestCaseHelper.skipBackgroundStepAndInjectSnapshotRestoreStep(testCase);
            } else {
                logger.debug("no background to skip");
            }
        } else {
            logger.debug("inject snapshot take step");
            lastFeaturePath = currentFeaturePath;
            hasBackground = CoreRunnerSnapshotTestCaseHelper.injectSnapshotTakeStep(testCase);
        }
    }

    @Override
    public String getName() {
        return "Snapshot";
    }

    @Override
    public int getPriority() {
        return 20;
    }

    @Override
    public void init0(EventPublisher publisher) {
        if (!SystemUtils.IS_OS_WINDOWS) {
            logger.info("<c>disable cucumber ct optimization globally since it only supported in windows platform now</c>");
            return;
        }
        // disable default due to lots of people occurring problem
        if ("true".equalsIgnoreCase(System.getProperty("enableCucumberCtOptimization"))) {
            ZwsSnapshotPluginImpl.setGlobalEnable(true);
            logger.info("<c>enable cucumber ct optimization globally</c>");
        } else {
            ZwsSnapshotPluginImpl.setGlobalEnable(false);
            logger.info("<c>disable cucumber ct optimization globally</c>");
        }
        publisher.registerHandlerFor(TestCaseStarted.class, ZwsSnapshotPluginImpl::handleTestCaseStarted);
    }

}
